﻿// --------------------------------------------------------------------------------------------------------------------
// <copyright file="MusicPlayer.cs" company="Jens Horstmann">
//   Copyright (c) Jens Horstmann. All rights reserved.
// </copyright>
// --------------------------------------------------------------------------------------------------------------------
namespace MiniMusicPlayer.Classes
{
    using System;
    using System.ComponentModel;
    using System.Diagnostics;
    using System.Linq;
    using System.Threading;
    using System.Timers;
    using System.Windows;
    using System.Windows.Forms;
    using System.Windows.Media;

    using Timer = System.Windows.Forms.Timer;

    /// <summary>
    /// The music player.
    /// </summary>
    public class MusicPlayer : INotifyPropertyChanged
    {
        private int lengthOfSong;

        private int progress;

        /// <summary>
        /// Initializes a new instance of the <see cref="MusicPlayer"/> class.
        /// </summary>
        public MusicPlayer()
        {
            this.MediaPlayer = new MediaPlayer();
            this.Playlist = new Playlist();

            this.MediaPlayer.MediaFailed += (sender, args) => { Debug.WriteLine(args.ErrorException.ToString()); };
            this.MediaPlayer.MediaEnded += (sender, args) => { this.SongEnded(); };

            var timer = new Timer() {Interval = 1000};
            timer.Tick += (sender, args) =>
                {
                    if (this.MediaPlayer.NaturalDuration.HasTimeSpan)
                    {
                        this.LengthOfSong = (int)this.MediaPlayer.NaturalDuration.TimeSpan.TotalMilliseconds;                        
                    }
                    else
                    {
                        this.LengthOfSong = int.MaxValue;
                    }

                    this.Progress = (int)this.MediaPlayer.Position.TotalMilliseconds;
                };
            timer.Start();
        }

        /// <summary>
        /// Gets the player.
        /// </summary>
        public MediaPlayer MediaPlayer { get; private set; }

        /// <summary>
        /// Gets the playlist.
        /// </summary>
        public Playlist Playlist { get; private set; }

        /// <summary>
        /// Gets a value indicating whether is paused.
        /// </summary>
        public bool IsPlaying { get; private set; }

        /// <summary>
        /// The song ended.
        /// </summary>
        private void SongEnded()
        {
            this.Play(this.Playlist.SongEnded());
        }

        public int Progress
        {
            get
            {
                return this.progress;
            }
            set
            {
                if (this.MediaPlayer.NaturalDuration.HasTimeSpan)
                {
                    this.progress = (int)((value / this.MediaPlayer.NaturalDuration.TimeSpan.TotalMilliseconds) * 100);
                }
                else
                {
                    this.progress = 0;
                }
                
                this.OnPropertyChanged("Progress");
            }
        }

        public int LengthOfSong
        {
            get
            {
                return this.lengthOfSong;
            }

            set
            {
                this.lengthOfSong = value;
                this.OnPropertyChanged("LengthOfSong");
            }
        }

        /// <summary>
        /// The play.
        /// </summary>
        /// <param name="song">
        /// The song.
        /// </param>
        public void Play(Song song = null)
        {
            if (song != null)
            {
                this.MediaPlayer.Open(new Uri(song.FileInfo.FullName));
                this.MediaPlayer.Play();
                this.Playlist.Play(song);
                this.IsPlaying = true;
            }
            else if (this.Playlist.ActualSong.Current != null)
            {
                if (this.MediaPlayer.HasAudio)
                {
                    this.MediaPlayer.Play();
                    this.IsPlaying = true;
                }
                else
                {
                    this.MediaPlayer.Open(new Uri(this.Playlist.ActualSong.Current.FileInfo.FullName));
                    this.MediaPlayer.Play();
                    this.IsPlaying = true;
                }
            }
            else
            {
                this.NextSong();
            }
        }

        /// <summary>
        /// The play playlist.
        /// </summary>
        public void PlayPlaylist()
        {
            this.Play(this.Playlist.Songs.FirstOrDefault());
        }

        /// <summary>
        /// The next song.
        /// </summary>
        public void NextSong()
        {
            if (this.Playlist.HasSongs)
            {
                var nextSong = this.Playlist.NextSong();
                this.Play(nextSong);
            }
        }

        /// <summary>
        /// The previous song.
        /// </summary>
        public void PreviousSong()
        {
            if (this.Playlist.HasSongs)
            {
                var prevSong = this.Playlist.PreviousSong();
                this.Play(prevSong);
            }
        }

        /// <summary>
        /// The pause.
        /// </summary>
        public void Pause()
        {
            if (this.MediaPlayer.CanPause)
            {
                this.MediaPlayer.Pause();
                this.IsPlaying = false;
            }
        }

        /// <summary>
        /// The play pause.
        /// </summary>
        public void PlayPause()
        {
            if (this.IsPlaying)
            {
                this.Pause();
            }
            else
            {
                this.Play();
            }
        }

        /// <summary>
        /// The stop.
        /// </summary>
        public void Stop()
        {
            this.MediaPlayer.Stop();
            this.Playlist.ActualSong.Stop();
        }

        /// <summary>
        /// The add song.
        /// </summary>
        /// <param name="song">
        /// The song.
        /// </param>
        public void AddSong(Song song)
        {
            this.Playlist.AddFile(song);
        }

        /// <summary>
        /// The mute.
        /// </summary>
        public void Mute()
        {
            this.MediaPlayer.IsMuted = !this.MediaPlayer.IsMuted;
        }

        /// <summary>
        /// The volume up.
        /// </summary>
        public void VolumeUp()
        {
            this.MediaPlayer.Volume += 0.025;
        }

        /// <summary>
        /// The volume down.
        /// </summary>
        public void VolumeDown()
        {
            this.MediaPlayer.Volume -= 0.025;
        }

        /// <summary>
        /// The remove song.
        /// </summary>
        /// <param name="song">
        /// The song.
        /// </param>
        internal void RemoveSong(Song song)
        {
            this.Playlist.RemoveSong(song);
        }

        protected void OnPropertyChanged(string name)
        {
            if (this.PropertyChanged != null)
            {
                this.PropertyChanged(this, new PropertyChangedEventArgs(name));
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;
    }
}